/**
 * 创建一个内联的Web Worker
 * @param workerFunction Worker函数的字符串表示
 * @returns Worker实例
 */
export function createInlineWorker(workerFunction: string): Worker {
  try {
    // 创建一个Blob，包含Worker的代码
    const blob = new Blob([workerFunction], { type: 'application/javascript' });
    
    // 从Blob创建一个URL
    const url = URL.createObjectURL(blob);
    
    // 创建Worker
    const worker = new Worker(url);
    
    // 当Worker终止时释放URL
    worker.addEventListener('error', (e) => {
      console.error('Worker error:', e);
    });
    
    // 添加终止时的清理
    const originalTerminate = worker.terminate;
    worker.terminate = function() {
      URL.revokeObjectURL(url);
      return originalTerminate.call(this);
    };
    
    return worker;
  } catch (error) {
    console.error('Failed to create inline worker:', error);
    throw error;
  }
}

// 导出Worker代码字符串
export const restorationWorkerCode = `
// Web Worker for image restoration
// This worker handles the CPU-intensive task of extracting original images from a stitched image

/**
 * Extract image data from stitched image data
 * @param stitchedImageData Stitched image data with ArrayBuffer
 * @param x X position
 * @param y Y position
 * @param width Width
 * @param height Height
 * @param stitchedWidth Width of stitched image
 * @param rotated Whether the image is rotated
 * @param originalWidth Original width before rotation
 * @param originalHeight Original height before rotation
 * @returns Extracted image data
 */
function extractImageData(
  stitchedImageData,
  x,
  y,
  width,
  height,
  stitchedWidth,
  rotated,
  originalWidth,
  originalHeight
) {
  // If the image is rotated, we need to create an image data with the original dimensions
  // Otherwise, use the dimensions from the metadata
  const outputWidth = rotated ? originalWidth : width;
  const outputHeight = rotated ? originalHeight : height;
  
  // Create new image data with the correct dimensions
  const imageData = new ImageData(outputWidth, outputHeight);

  // Convert ArrayBuffer to Uint8ClampedArray for easier access
  const sourceData = new Uint8ClampedArray(stitchedImageData.data);

  // Copy pixel data
  if (rotated) {
    // For rotated images, we need to rotate the pixels back to their original orientation
    for (let row = 0; row < outputHeight; row++) {
      for (let col = 0; col < outputWidth; col++) {
        // In the stitched image, the rotated image has its rows and columns swapped
        // For a 90-degree clockwise rotation, to map back we need to:
        // srcRow = col
        // srcCol = height - row - 1
        // But since our image is already rotated in the stitched image,
        // we need to use the rotated dimensions (width and height are swapped)
        const srcRow = col;
        const srcCol = width - row - 1;
        
        // Calculate positions in source and destination arrays
        const srcPos = ((y + srcRow) * stitchedWidth + (x + srcCol)) * 4;
        const destPos = (row * outputWidth + col) * 4;

        // Copy RGBA values
        imageData.data[destPos] = sourceData[srcPos];         // R
        imageData.data[destPos + 1] = sourceData[srcPos + 1]; // G
        imageData.data[destPos + 2] = sourceData[srcPos + 2]; // B
        imageData.data[destPos + 3] = sourceData[srcPos + 3]; // A
      }
    }
  } else {
    // For non-rotated images, just copy the pixels directly
    for (let row = 0; row < height; row++) {
      for (let col = 0; col < width; col++) {
        // Calculate positions in source and destination arrays
        const srcPos = ((y + row) * stitchedWidth + (x + col)) * 4;
        const destPos = (row * width + col) * 4;

        // Copy RGBA values
        imageData.data[destPos] = sourceData[srcPos];         // R
        imageData.data[destPos + 1] = sourceData[srcPos + 1]; // G
        imageData.data[destPos + 2] = sourceData[srcPos + 2]; // B
        imageData.data[destPos + 3] = sourceData[srcPos + 3]; // A
      }
    }
  }

  return imageData;
}

// Handle messages from the main thread
self.onmessage = async (e) => {
  const { stitchedImageData, metadata } = e.data;

  if (!stitchedImageData || !metadata) {
    self.postMessage({
      type: 'error',
      data: { message: '缺少必要的数据' }
    });
    return;
  }

  try {
    // Send initial progress
    self.postMessage({ type: 'progress', data: 0 });

    // Create array for restored images
    const restoredImages = [];

    // Process each image position from metadata
    const totalImages = metadata.images.length;

    for (let i = 0; i < totalImages; i++) {
      const imagePos = metadata.images[i];

      // Extract image data from stitched image
      const imageData = extractImageData(
        stitchedImageData,
        imagePos.x,
        imagePos.y,
        imagePos.width,
        imagePos.height,
        metadata.stitchedImageSize.width,
        imagePos.rotated,
        imagePos.originalWidth,
        imagePos.originalHeight
      );

      // Create restored image object
      const restoredImage = {
        id: imagePos.id,
        name: imagePos.name,
        width: imagePos.rotated ? imagePos.originalWidth : imagePos.width,
        height: imagePos.rotated ? imagePos.originalHeight : imagePos.height,
        format: imagePos.format,
        imageData
      };

      // Add to restored images array
      restoredImages.push(restoredImage);

      // Update progress
      self.postMessage({
        type: 'progress',
        data: Math.round(((i + 1) / totalImages) * 100)
      });
    }

    // Convert ImageData to transferable format
    const transferableRestoredImages = restoredImages.map(img => {
      // Create a copy of the image data buffer
      const buffer = img.imageData.data.buffer.slice(0);

      return {
        id: img.id,
        name: img.name,
        width: img.width,
        height: img.height,
        format: img.format,
        imageDataBuffer: buffer,
      };
    });

    // Create list of transferable objects
    const transferables = transferableRestoredImages.map(img => img.imageDataBuffer);

    // Send final result with transferable objects
    self.postMessage({
      type: 'complete',
      data: {
        restoredImages: transferableRestoredImages
      }
    }, transferables);
  } catch (error) {
    self.postMessage({
      type: 'error',
      data: { message: error.message || '还原过程中发生错误' }
    });
  }
};
`;

export const stitchingWorkerCode = `
// Web Worker for image stitching
// This worker handles the CPU-intensive task of stitching images together

/**
 * 检查一组图片的尺寸是否相似
 * @param images 图片数组
 * @returns 是否相似
 */
function areSimilarSizes(images) {
  if (images.length <= 1) return true;

  const firstWidth = images[0].width;
  const firstHeight = images[0].height;

  // 允许10%的误差
  const tolerance = 0.1;

  return images.every(img =>
    Math.abs(img.width - firstWidth) / firstWidth < tolerance &&
    Math.abs(img.height - firstHeight) / firstHeight < tolerance
  );
}

/**
 * Calculate optimal grid dimensions for a given number of images
 * @param count Number of images
 * @returns [rows, columns]
 */
function calculateGridDimensions(count) {
  const sqrt = Math.sqrt(count);
  const cols = Math.ceil(sqrt);
  const rows = Math.ceil(count / cols);
  return [rows, cols];
}

/**
 * Calculate dimensions and positions for stitched image
 * @param images Images to stitch
 * @param options Stitching options
 * @returns Object with width, height, and positions
 */
function calculateDimensions(images, options) {
  const { arrangement, spacing } = options;
  const positions = [];
  
  let totalWidth = 0;
  let totalHeight = 0;
  
  if (arrangement === 'horizontal') {
    // All images in a row
    let currentX = 0;
    let maxHeight = 0;
    
    for (const image of images) {
      positions.push({
        id: image.id,
        name: image.name,
        x: currentX,
        y: 0,
        width: image.width,
        height: image.height,
        format: image.format
      });
      
      currentX += image.width + spacing;
      maxHeight = Math.max(maxHeight, image.height);
    }
    
    totalWidth = currentX - spacing; // Remove last spacing
    totalHeight = maxHeight;
  } else if (arrangement === 'vertical') {
    // All images in a column
    let currentY = 0;
    let maxWidth = 0;
    
    for (const image of images) {
      positions.push({
        id: image.id,
        name: image.name,
        x: 0,
        y: currentY,
        width: image.width,
        height: image.height,
        format: image.format
      });
      
      currentY += image.height + spacing;
      maxWidth = Math.max(maxWidth, image.width);
    }
    
    totalWidth = maxWidth;
    totalHeight = currentY - spacing; // Remove last spacing
  } else if (arrangement === 'dynamic') {
    // 动态布局 - 尝试创建接近正方形的布局
    // 将图片分为横向和纵向两组
    const landscapeImages = images.filter(img => img.width > img.height);
    const portraitImages = images.filter(img => img.height > img.width);
    
    // 检查是否所有图片尺寸相似
    const isLandscapeSimilar = areSimilarSizes(landscapeImages);
    const isPortraitSimilar = areSimilarSizes(portraitImages);
    
    // 如果横向和纵向图片都有，并且尺寸相似，尝试创建接近正方形的布局
    if (landscapeImages.length > 0 && portraitImages.length > 0 && 
        isLandscapeSimilar && isPortraitSimilar) {
      
      // 获取典型图片尺寸
      const typicalLandscape = landscapeImages[0];
      const typicalPortrait = portraitImages[0];
      
      // 检查横向图片的宽是否约等于纵向图片的高，横向图片的高是否约等于纵向图片的宽
      const isComplementary = Math.abs(typicalLandscape.width - typicalPortrait.height) < 100 &&
                             Math.abs(typicalLandscape.height - typicalPortrait.width) < 100;
      
      if (isComplementary) {
        // 创建接近正方形的布局
        // 为了确保布局是接近正方形的，我们将旋转所有的纵向图片
        
        // 记录旋转信息
        const rotations = {};
        portraitImages.forEach(img => {
          rotations[img.id] = true;
        });
        
        // 计算每行可以放置的图片数量
        const landscapeWidth = typicalLandscape.width;
        const imagesPerRow = Math.floor(12000 / landscapeWidth);
        
        // 所有图片（横向图片和旋转后的纵向图片）
        const allImages = [
          ...landscapeImages,
          ...portraitImages.map(img => ({
            ...img,
            width: img.height, // 旋转后宽高交换
            height: img.width,
            rotated: true
          }))
        ];
        
        // 按行放置图片
        let currentX = 0;
        let currentY = 0;
        let rowHeight = 0;
        
        for (let i = 0; i < allImages.length; i++) {
          const img = allImages[i];
          
          // 如果这是一个新行的开始或者当前行放不下这张图片
          if (currentX === 0 || currentX + img.width > 12000) {
            // 如果不是第一行，移到下一行
            if (currentX > 0) {
              currentX = 0;
              currentY += rowHeight + spacing;
            }
            rowHeight = 0;
          }
          
          // 放置图片
          positions.push({
            id: img.id,
            name: img.name,
            x: currentX,
            y: currentY,
            width: img.width,
            height: img.height,
            format: img.format,
            rotated: img.rotated
          });
          
          // 更新当前位置和行高
          currentX += img.width + spacing;
          rowHeight = Math.max(rowHeight, img.height);
        }
        
        // 计算布局的实际宽度和高度
        totalWidth = Math.min(12000, Math.max(...positions.map(p => p.x + p.width)));
        totalHeight = Math.max(...positions.map(p => p.y + p.height));
        
        return { width: totalWidth, height: totalHeight, positions };
      }
    }
    
    // 如果不是特殊情况，使用默认的网格布局
    const [_, cols] = calculateGridDimensions(images.length);
    
    let currentX = 0;
    let currentY = 0;
    let maxRowHeight = 0;
    let maxWidth = 0;
    
    for (let i = 0; i < images.length; i++) {
      const image = images[i];
      
      // If we've reached the end of a row, move to the next row
      if (i > 0 && i % cols === 0) {
        currentX = 0;
        currentY += maxRowHeight + spacing;
        maxRowHeight = 0;
      }
      
      positions.push({
        id: image.id,
        name: image.name,
        x: currentX,
        y: currentY,
        width: image.width,
        height: image.height,
        format: image.format
      });
      
      currentX += image.width + spacing;
      maxRowHeight = Math.max(maxRowHeight, image.height);
      maxWidth = Math.max(maxWidth, currentX - spacing);
    }
    
    totalWidth = maxWidth;
    totalHeight = currentY + maxRowHeight;
  } else {
    // Grid arrangement
    const [_, cols] = calculateGridDimensions(images.length);
    
    let currentX = 0;
    let currentY = 0;
    let maxRowHeight = 0;
    let maxWidth = 0;
    
    for (let i = 0; i < images.length; i++) {
      const image = images[i];
      
      // If we've reached the end of a row, move to the next row
      if (i > 0 && i % cols === 0) {
        currentX = 0;
        currentY += maxRowHeight + spacing;
        maxRowHeight = 0;
      }
      
      positions.push({
        id: image.id,
        name: image.name,
        x: currentX,
        y: currentY,
        width: image.width,
        height: image.height,
        format: image.format
      });
      
      currentX += image.width + spacing;
      maxRowHeight = Math.max(maxRowHeight, image.height);
      maxWidth = Math.max(maxWidth, currentX - spacing);
    }
    
    totalWidth = maxWidth;
    totalHeight = currentY + maxRowHeight;
  }
  
  // Ensure dimensions don't exceed limits
  totalWidth = Math.min(totalWidth, options.maxWidth);
  totalHeight = Math.min(totalHeight, options.maxHeight);
  
  return { width: totalWidth, height: totalHeight, positions };
}

// Handle messages from the main thread
self.onmessage = async (e) => {
  const { images, options } = e.data;
  
  if (!images || images.length === 0) {
    self.postMessage({ 
      type: 'error', 
      data: { message: '没有图片可拼接' } 
    });
    return;
  }
  
  try {
    // Send initial progress
    self.postMessage({ type: 'progress', data: 0 });
    
    // Calculate dimensions and positions
    const { width, height, positions } = calculateDimensions(images, options);
    
    // Since we can't directly create and manipulate canvas in a worker,
    // we'll send the calculated positions back to the main thread
    // and let it handle the actual drawing
    
    // Send progress updates
    self.postMessage({ type: 'progress', data: 50 });
    
    // Simulate some processing time
    await new Promise(resolve => setTimeout(resolve, 500));
    
    // Send final result
    self.postMessage({
      type: 'complete',
      data: {
        width,
        height,
        positions,
        backgroundColor: options.backgroundColor
      }
    });
  } catch (error) {
    self.postMessage({ 
      type: 'error', 
      data: { message: error.message || '拼接过程中发生错误' } 
    });
  }
};
`;